Skip to content

feat(next): integrate Intercom provider lifecycle in app layout#2162

Open
niemyjski wants to merge 7 commits intomainfrom
feature/next-intercom
Open

feat(next): integrate Intercom provider lifecycle in app layout#2162
niemyjski wants to merge 7 commits intomainfrom
feature/next-intercom

Conversation

@niemyjski
Copy link
Member

Summary

  • Integrates Intercom via svelte-intercom into the authenticated app shell so user/org context can be booted reactively from real app data.
  • Hides the default Intercom launcher and disables noise-related features by default to align with in-app UX.
  • Ensures logout and auth-state transitions shut down Intercom cleanly to avoid cross-user/session bleed.

Root Cause (if bug fix)

  • N/A (feature work).

What I Changed and Why

  • Added a dedicated Intercom feature slice (context, keys, initializer) so all Intercom boot/update/shutdown behavior is centralized and reusable.
  • Wired the initializer into the (app) layout to guarantee Intercom lifecycle follows authenticated route lifecycle and project/org navigation.
  • Updated auth API logout path to explicitly trigger Intercom shutdown behavior, preventing stale messenger state after sign-out.
  • Threaded Intercom context inputs from usage/configure pages so account/user metadata stays current as users navigate.
  • Added package dependencies in package.json/package-lock.json required for the Svelte integration.

Tech Debt Assessment

  • No deliberate shortcuts introduced; integration is additive and isolated to a feature slice.
  • Future improvement: add dedicated integration tests for boot option mapping and logout shutdown edge cases.

Test Plan

  • cd src/Exceptionless.Web/ClientApp && npm run check
  • cd src/Exceptionless.Web/ClientApp && npm run test:unit
  • Dogfood /next authenticated flow to validate Intercom behavior in-browser.

Copilot AI review requested due to automatic review settings March 17, 2026 13:27
@niemyjski niemyjski self-assigned this Mar 17, 2026
@niemyjski niemyjski force-pushed the feature/next-intercom branch from bdb3437 to 5d05bad Compare March 17, 2026 13:29
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces an Intercom integration for the SvelteKit “(app)” shell so support chat can be launched from within the new ClientApp UI, and normalizes a few Tailwind sizing utilities in usage pages.

Changes:

  • Add an Intercom provider/initializer wrapper in the authenticated app layout and expose an openChat callback to downstream UI.
  • Add an Intercom feature module ($features/intercom) to build boot options and expose the Intercom context.
  • Replace a few arbitrary Tailwind sizes (h-[200px], h-[250px], min-w-[230px]) with equivalent spacing-based classes.

Reviewed changes

Copilot reviewed 10 out of 11 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/usage/+page.svelte Normalize skeleton/chart/tooltip sizing classes.
src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/configure/+page.svelte Wire “contact support” action to Intercom context when available.
src/Exceptionless.Web/ClientApp/src/routes/(app)/organization/[organizationId]/usage/+page.svelte Normalize skeleton/chart/tooltip sizing classes.
src/Exceptionless.Web/ClientApp/src/routes/(app)/+layout.svelte Add IntercomProvider + initializer and pass openChat into the app shell/notifications.
src/Exceptionless.Web/ClientApp/src/lib/features/intercom/keys.ts Define a shared context key for Intercom.
src/Exceptionless.Web/ClientApp/src/lib/features/intercom/intercom-initializer.svelte New wrapper component to manage Intercom update cadence, routing updates, and shutdown on logout.
src/Exceptionless.Web/ClientApp/src/lib/features/intercom/index.ts Public exports for the intercom feature module.
src/Exceptionless.Web/ClientApp/src/lib/features/intercom/context.svelte.ts Add getIntercom() and a helper to build boot options from current user/org.
src/Exceptionless.Web/ClientApp/src/lib/features/auth/api.svelte.ts Remove an extraneous stray diff artifact line.
src/Exceptionless.Web/ClientApp/package.json Add svelte-intercom dependency.
src/Exceptionless.Web/ClientApp/package-lock.json Lockfile updates for svelte-intercom and transitive dependency version bumps.
Files not reviewed (1)
  • src/Exceptionless.Web/ClientApp/package-lock.json: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

…ippet

- Consolidate redundant intercom.update() calls into single effect tracking route and visibility
- Extract getIntercom() into separate snippet to avoid context scoping issues
- Both changes prevent duplicate updates and ensure context is properly available
@niemyjski niemyjski requested review from Copilot and ejsmith March 19, 2026 03:51
Root cause: the sidebar support action was opening a fresh composer instead of the existing message history, and the new auth test needed immediate consistency so the seeded user was visible before login. The current staged set also carries the Intercom boot/auth wiring that this branch has been validating.
@niemyjski niemyjski force-pushed the feature/next-intercom branch from e4683c6 to 38f6705 Compare March 19, 2026 03:58
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds an Intercom integration to the /next authenticated SvelteKit app shell by introducing a dedicated Intercom feature slice, wiring provider/initializer lifecycle into the (app) layout, and adding a backend endpoint to mint Intercom JWTs for the current user.

Changes:

  • Add /api/v2/auth/intercom endpoint to return an Intercom JWT for the authenticated user, plus integration tests.
  • Introduce a new $features/intercom slice (boot option builder, context key/getter, initializer component) and integrate it into the (app) layout with unread count support.
  • Add svelte-intercom dependency and thread “open chat” behavior into UI entry points.

Reviewed changes

Copilot reviewed 16 out of 17 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tests/Exceptionless.Tests/Controllers/AuthControllerTests.cs Adds integration tests for the new auth/intercom endpoint.
src/Exceptionless.Web/Exceptionless.Web.csproj Adds System.IdentityModel.Tokens.Jwt package for server-side JWT creation.
src/Exceptionless.Web/Controllers/AuthController.cs Adds GET auth/intercom endpoint that issues an Intercom JWT for CurrentUser.
src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/usage/+page.svelte Updates Tailwind sizing utilities for skeleton/chart/tooltip.
src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/configure/+page.svelte Wires “contact support” to Intercom context showMessages().
src/Exceptionless.Web/ClientApp/src/routes/(app)/organization/[organizationId]/usage/+page.svelte Updates Tailwind sizing utilities for skeleton/chart/tooltip.
src/Exceptionless.Web/ClientApp/src/routes/(app)/+layout.svelte Adds Intercom provider + initializer lifecycle integration and unread count plumbing.
src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/sidebar-user.svelte Adds chat entry points + unread badge in the user/sidebar menu.
src/Exceptionless.Web/ClientApp/src/lib/features/intercom/keys.ts Defines the Intercom context key.
src/Exceptionless.Web/ClientApp/src/lib/features/intercom/intercom-initializer.svelte Adds Intercom update interval, route-sync updates, and logout shutdown behavior.
src/Exceptionless.Web/ClientApp/src/lib/features/intercom/index.ts Exposes Intercom feature exports for layout/pages.
src/Exceptionless.Web/ClientApp/src/lib/features/intercom/context.svelte.ts Implements boot option builder and getIntercom() context accessor.
src/Exceptionless.Web/ClientApp/src/lib/features/intercom/context.svelte.test.ts Adds unit tests for Intercom boot option mapping.
src/Exceptionless.Web/ClientApp/src/lib/features/auth/index.svelte.ts Re-exports getIntercomTokenQuery.
src/Exceptionless.Web/ClientApp/src/lib/features/auth/api.svelte.ts Adds getIntercomTokenQuery() that calls auth/intercom.
src/Exceptionless.Web/ClientApp/package.json Adds svelte-intercom dependency.
src/Exceptionless.Web/ClientApp/package-lock.json Updates lockfile for svelte-intercom and other transitive dependency changes.
Files not reviewed (1)
  • src/Exceptionless.Web/ClientApp/package-lock.json: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Adds JWT expiration (1 hour) and issued-at claims to the Intercom token on the backend.
- Configures the frontend query to automatically refresh the token every 55 minutes to ensure continuous authentication.
- Centralizes help and documentation links and provides a fallback to GitHub issues when the Intercom messenger is unavailable or disabled.
Copilot AI review requested due to automatic review settings March 19, 2026 13:19
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR integrates Intercom into the authenticated SvelteKit app shell so the messenger boots/updates/shuts down based on real user/org state, backed by a new API endpoint that issues an Intercom user JWT.

Changes:

  • Added GET /api/v2/auth/intercom to mint a signed Intercom user JWT for the current authenticated user, plus integration tests.
  • Introduced a dedicated ClientApp Intercom feature slice (boot option builder, initializer/provider context, chat helper) and wired it into the (app) layout lifecycle (including unread count wiring).
  • Centralized “Help” links into a shared module and updated a few UI sizing classes.

Reviewed changes

Copilot reviewed 23 out of 24 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tests/Exceptionless.Tests/Controllers/AuthControllerTests.cs Adds integration tests for the new /auth/intercom token endpoint.
src/Exceptionless.Web/Exceptionless.Web.csproj Adds JWT package dependency needed for Intercom token minting.
src/Exceptionless.Web/Controllers/AuthController.cs Adds GET auth/intercom to return a signed Intercom JWT for the current user.
src/Exceptionless.Web/ClientApp/src/routes/(app)/routes.svelte.ts Uses centralized help-link constants instead of hardcoded URLs.
src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/usage/+page.svelte Updates chart/skeleton sizing utility classes.
src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/configure/+page.svelte Hooks “contact support” to Intercom/open-support fallback.
src/Exceptionless.Web/ClientApp/src/routes/(app)/organization/[organizationId]/usage/+page.svelte Updates chart/skeleton sizing utility classes.
src/Exceptionless.Web/ClientApp/src/routes/(app)/+layout.svelte Adds IntercomProvider + initializer and wires auth/org context + unread count into the app shell.
src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/sidebar-user.svelte Adds chat entrypoint + unread badge and uses centralized help links.
src/Exceptionless.Web/ClientApp/src/lib/features/shared/help-links.ts New shared constants for documentation/support/repo/API reference URLs.
src/Exceptionless.Web/ClientApp/src/lib/features/intercom/keys.ts Defines the Intercom context key.
src/Exceptionless.Web/ClientApp/src/lib/features/intercom/intercom-initializer.svelte Manages Intercom update cadence, route updates, and logout shutdown.
src/Exceptionless.Web/ClientApp/src/lib/features/intercom/index.ts Barrel exports for the Intercom feature slice.
src/Exceptionless.Web/ClientApp/src/lib/features/intercom/context.svelte.ts Builds Intercom boot options and exposes getIntercom() context accessor.
src/Exceptionless.Web/ClientApp/src/lib/features/intercom/context.svelte.test.ts Unit tests for boot option mapping.
src/Exceptionless.Web/ClientApp/src/lib/features/intercom/config.ts Defines token refresh cadence constants.
src/Exceptionless.Web/ClientApp/src/lib/features/intercom/config.test.ts Unit tests for refresh cadence constants.
src/Exceptionless.Web/ClientApp/src/lib/features/intercom/chat.ts Adds openSupportChat helper with Intercom + fallback behavior.
src/Exceptionless.Web/ClientApp/src/lib/features/intercom/chat.test.ts Unit tests for chat helper behavior.
src/Exceptionless.Web/ClientApp/src/lib/features/auth/index.svelte.ts Re-exports getIntercomTokenQuery.
src/Exceptionless.Web/ClientApp/src/lib/features/auth/api.svelte.ts Adds TanStack Query wrapper for fetching/refreshing the Intercom token.
src/Exceptionless.Web/ClientApp/package.json Adds svelte-intercom dependency.
src/Exceptionless.Web/ClientApp/package-lock.json Locks svelte-intercom and updates various transitive dependencies.
.claude/agents/triage.md Updates internal triage workflow wording/instructions.
Files not reviewed (1)
  • src/Exceptionless.Web/ClientApp/package-lock.json: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Root cause: the Intercom token query reused a static cache key across auth-session changes, and the new auth/intercom contract updates were missing their HTTP and OpenAPI baselines.
Root cause: the initial package-lock regeneration pulled in unrelated transitive resolver updates instead of only recording the new Intercom packages required by the feature.
Copilot AI review requested due to automatic review settings March 19, 2026 13:47
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR integrates Intercom into the authenticated “next” app shell by adding a backend endpoint for Intercom messenger JWTs and wiring an Intercom provider/initializer into the Svelte layout so Intercom boots/updates/shuts down with auth + navigation state.

Changes:

  • Added GET /api/v2/auth/intercom to mint an Intercom JWT for the current authenticated user, with OpenAPI + integration test coverage.
  • Introduced a dedicated ClientApp Intercom feature slice (boot option builder, context access, initializer lifecycle, chat helper) and integrated it into the (app) layout + relevant pages.
  • Centralized external help/support links and added svelte-intercom dependency.

Reviewed changes

Copilot reviewed 25 out of 26 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
tests/http/auth.http Updates auth HTTP examples; adds request for /auth/intercom.
tests/Exceptionless.Tests/Controllers/Data/openapi.json Updates OpenAPI snapshot with /api/v2/auth/intercom.
tests/Exceptionless.Tests/Controllers/AuthControllerTests.cs Adds integration tests for Intercom token success + disabled scenarios.
src/Exceptionless.Web/Exceptionless.Web.csproj Adds System.IdentityModel.Tokens.Jwt dependency for token minting.
src/Exceptionless.Web/Controllers/AuthController.cs Implements /auth/intercom endpoint that returns a signed JWT.
src/Exceptionless.Web/ClientApp/src/routes/(app)/routes.svelte.ts Uses shared help-link constants for Help routes.
src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/usage/+page.svelte Updates chart/skeleton sizing classes.
src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/configure/+page.svelte Hooks “open chat” into Intercom context via feature helper.
src/Exceptionless.Web/ClientApp/src/routes/(app)/organization/[organizationId]/usage/+page.svelte Updates chart/skeleton sizing classes.
src/Exceptionless.Web/ClientApp/src/routes/(app)/+layout.svelte Adds IntercomProvider + IntercomInitializer and propagates chat/unread state into sidebar.
src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/sidebar-user.svelte Adds chat entry + unread badge; switches help links to constants.
src/Exceptionless.Web/ClientApp/src/lib/features/shared/help-links.ts New: central constants for documentation/support/GitHub/API links.
src/Exceptionless.Web/ClientApp/src/lib/features/intercom/* New: Intercom context key, initializer lifecycle, boot options builder, config, chat helper, unit tests.
src/Exceptionless.Web/ClientApp/src/lib/features/auth/index.svelte.ts Re-exports getIntercomTokenQuery.
src/Exceptionless.Web/ClientApp/src/lib/features/auth/api.svelte.ts Adds getIntercomTokenQuery with refresh cadence.
src/Exceptionless.Web/ClientApp/package.json Adds svelte-intercom.
src/Exceptionless.Web/ClientApp/package-lock.json Locks svelte-intercom + @intercom/messenger-js-sdk.
.claude/agents/triage.md Updates internal triage agent guidance text.
Files not reviewed (1)
  • src/Exceptionless.Web/ClientApp/package-lock.json: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +161 to +172
/// <summary>
/// Get the current user's Intercom messenger token.
/// </summary>
/// <response code="200">Intercom messenger token</response>
/// <response code="422">Intercom is not configured</response>
[HttpGet("intercom")]
public Task<ActionResult<TokenResult>> GetIntercomTokenAsync()
{
if (!_intercomOptions.EnableIntercom || String.IsNullOrWhiteSpace(_intercomOptions.IntercomSecret))
{
ModelState.AddModelError("intercom", "Intercom is not enabled.");
return Task.FromResult<ActionResult<TokenResult>>(ValidationProblem(ModelState));
Comment on lines +297 to +309
{#if isAuthenticated}
{#if isChatEnabled}
<IntercomProvider
appId={intercomAppId}
autoboot={shouldBootIntercom}
bootOptions={intercomBootOptions}
onUnreadCountChange={onIntercomUnreadCountChange}
>
{@render intercomShell()}
</IntercomProvider>
{:else}
{@render appShell(openChatFallback)}
{/if}
<div class="space-y-4">
<Skeleton class="h-12 w-3/4" />
<Skeleton class="h-[200px] w-full" />
<Skeleton class="h-50 w-full" />
</div>

<Chart.Container config={chartConfig} class="aspect-auto h-[250px] w-full">
<Chart.Container config={chartConfig} class="aspect-auto h-62.5 w-full">
>
{#snippet tooltip()}
<Chart.Tooltip class="min-w-[230px]" indicator="line" labelFormatter={(v) => formatDateLabel(v as Date)} />
<Chart.Tooltip class="min-w-57.5" indicator="line" labelFormatter={(v) => formatDateLabel(v as Date)} />
<div class="space-y-4">
<Skeleton class="h-12 w-3/4" />
<Skeleton class="h-[200px] w-full" />
<Skeleton class="h-50 w-full" />
</div>

<Chart.Container config={chartConfig} class="aspect-auto h-[250px] w-full">
<Chart.Container config={chartConfig} class="aspect-auto h-62.5 w-full">
>
{#snippet tooltip()}
<Chart.Tooltip class="min-w-[230px]" indicator="line" labelFormatter={(v) => formatDateLabel(v as Date)} />
<Chart.Tooltip class="min-w-57.5" indicator="line" labelFormatter={(v) => formatDateLabel(v as Date)} />
@github-actions
Copy link

Code Coverage

Package Line Rate Branch Rate Complexity Health
Exceptionless.Insulation 24% 23% 208
Exceptionless.Core 66% 60% 7546
Exceptionless.AppHost 26% 14% 55
Exceptionless.Web 57% 43% 3602
Summary 61% (11897 / 19413) 54% (5912 / 10964) 11411

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

2 participants